package cc.uraniummc.updater;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Map;

import cc.uraniummc.Uranium;
import cc.uraniummc.ULog;
import cc.uraniummc.entity.UraniumAPISoft;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import lombok.val;
import net.minecraft.server.MinecraftServer;

import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.simple.parser.JSONParser;

import static java.nio.charset.StandardCharsets.UTF_8;

public class UVersionRetriever implements Runnable, UncaughtExceptionHandler {
    private static final boolean DEBUG;
    private static final ULog sLogger;
    private static final JSONParser sParser;
    private static MinecraftServer sServer;

    static {
        DEBUG = false;
        sLogger = ULog.get(UVersionRetriever.class.getSimpleName());

        sParser = new JSONParser();
    }

    public static void init(MinecraftServer server) {
        sServer = server;
        if (MinecraftServer.uraniumConfig.updatecheckerEnable.getValue()) {
            startServer(DefaultUpdateCallback.INSTANCE, true);
        }
    }

    public static void startServer(IVersionCheckCallback callback, boolean loop) {
        new UVersionRetriever(callback, loop, true, Uranium.getGroup(),
                Uranium.getChannel());
    }

    private final IVersionCheckCallback mCallback;
    private final boolean mLoop;
    private final Thread mThread;
    private final String mGroup;
    private final String mName;
    private final boolean mUpToDateSupport;

    public UVersionRetriever(IVersionCheckCallback callback, boolean loop,
                             boolean upToDateSupport, String group, String name) {
        if (DEBUG)
            sLogger.info("Created new version retrivier");
        mCallback = callback;
        mLoop = loop;
        mUpToDateSupport = upToDateSupport;
        mGroup = group;
        mName = name;
        mThread = new Thread(Uranium.sKCauldronThreadGroup, this, "Uranium version retrievier");
        mThread.setPriority(Thread.MIN_PRIORITY);
        mThread.setDaemon(true);
        mThread.setUncaughtExceptionHandler(this);
        mThread.start();
    }

    @Override
    public void run() {
        while (!mThread.isInterrupted()) {
            check();
            if (!mLoop)
                break;
            try {
                Thread.sleep(1000 * 60 * 10);// Sleep ten minutes
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    private void check() {
        try {
            val gson=new Gson();
            val client=HttpClientBuilder.create().setUserAgent("Uranium "+Uranium.getCurrentVersion()).build();
            val request=RequestBuilder.get("https://api.uraniummc.cc/softs/json/soft_list.json")
                    .setCharset(UTF_8)
                    .build();
            Integer sid=Uranium.getBranch().equals("dev")?2:1;
            val req=client.execute(request);
            try{
                val R=new InputStreamReader(req.getEntity().getContent(),UTF_8);
                val list=gson.fromJson(R,JsonObject.class);
                val obj=list.getAsJsonObject(sid.toString());
                if(obj!=null){
                    val soft=gson.fromJson(obj,UraniumAPISoft.class);
                    try {
                        val B = Uranium.getCurrentVersion().split("-")[3];
                        val build = Integer.valueOf(B.substring(1));
                        if(build<soft.getLeast_build()){
                            mCallback.newVersion(Uranium.getBranch()+" B"+soft.getVersion());
                        }else{
                            mCallback.upToDate();
                        }
                    }catch (Exception e){
                        mCallback.error(new Exception("Invaild local version",e));
                    }
                }
            }catch (IOException e){
                mCallback.error(e);
            }finally {
                if(req!=null)req.close();
            }

            /*
            HttpUriRequest request = RequestBuilder
                    .get()
                    .setUri("https://api.prok.pw/repo/version/" + mGroup + "/"
                            + mName)
                    .addParameter("version", Uranium.getCurrentVersion())
                    .addParameter("hostname", sServer.getHostname())
                    .addParameter("port", "" + sServer.getPort()).build();
            HttpResponse response = HttpClientBuilder.create()
                    .setUserAgent("Uranium Version Retriever")
                    .setRedirectStrategy(new LaxRedirectStrategy()).build()
                    .execute(request);
            if (response.getStatusLine().getStatusCode() != 200) {
                uncaughtException(mThread, new IllegalStateException(
                        "Status code isn't OK"));
                return;
            }
            JSONObject json = (JSONObject) sParser.parse(new InputStreamReader(
                    response.getEntity().getContent()));
            String version = (String) json.get("version");
            if (!mUpToDateSupport || Uranium.getCurrentVersion() == null
                    || !version.equals(Uranium.getCurrentVersion())) {
                mCallback.newVersion(version);
            } else {
                mCallback.upToDate();
            }
            */
        } catch (Exception e) {
            uncaughtException(null, e);
        }
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        sLogger.warning(e, "Error occured during retriving version");
        if (mCallback != null) {
            mCallback.error(e);
        }
    }

    public interface IVersionCheckCallback {
        void upToDate();

        void newVersion(String newVersion);

        void error(Throwable t);
    }
}
